package com.sg.service.biz.framework.nb;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.sg.common.util.CommonFunctionHelper;
import com.sg.dto.biz.framework.common.BaseChangeColDto;
import com.sg.dto.biz.framework.req.*;
import com.sg.dto.biz.framework.res.*;
import com.sg.dto.integration.component.QuerySemanticEngineDetailReqDto;
import com.sg.dto.integration.component.QuerySemanticEngineDetailRespDto;
import com.wicket.okrcomponent.common.annotations.BanAuto;
import com.wicket.okrcomponent.integration.TemplateEngineService;
import com.wicket.okrframework.common.exception.BizException;
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Tags;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author ： 手工接入方法
 * @version 1.0
 * @since 2022/5/28 15:32
 */
@Service
public class NbChangeColumn {

    @Resource
    private DataSource dataSource;

    @Resource
    private TemplateEngineService fwCompTemplateEngineClient;

    /**
     * code:dataAuClassification
     * name:从更新字段中，过滤新增、修改字段（空方法）
     * desc:undefined
     **/
    @BanAuto
    @Trace(operationName = "从更新字段中，过滤新增、修改字段（空方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public FilterAddUpdateColumnRespDto filterAddUpdateColumn(FilterAddUpdateColumnReqDto reqDto) {
        FilterAddUpdateColumnRespDto retData = new FilterAddUpdateColumnRespDto();
        List<NewColumnDto> addList = new ArrayList<>();
        List<ModifyColumnDto> changeList = new ArrayList<>();
        Map<String, BaseChangeColumnDto> index = new HashMap<>();
        if (CollUtil.isEmpty(reqDto.getChangeColumnList())) {
            return retData;
        }
        if (CollUtil.isEmpty(reqDto.getBaseChangeColumnList())) {
            for (ChangeColumnDto one : reqDto.getChangeColumnList()) {
                NewColumnDto base = new NewColumnDto();
                BeanUtil.copyProperties(one, base);
                addList.add(base);
            }
            retData.setNewColumnList(addList);
            return retData;
        }

        for (BaseChangeColumnDto oneBase : reqDto.getBaseChangeColumnList()) {
            index.put(oneBase.getObjectPropertyCode(), oneBase);
        }

        for (ChangeColumnDto oneChange : reqDto.getChangeColumnList()) {
            BaseChangeColumnDto dbData = index.get(oneChange.getObjectPropertyCode());
            if (dbData == null) {
                NewColumnDto base = new NewColumnDto();
                BeanUtil.copyProperties(oneChange, base);
                addList.add(base);
            } else {
                ModifyColumnDto change = new ModifyColumnDto();
                BeanUtil.copyProperties(oneChange, change);
                change.setChangeColumnId(dbData.getChangeColumnId());
                changeList.add(change);
            }
        }
        retData.setNewColumnList(addList);
        retData.setModifyColumnList(changeList);
        return retData;
    }

    /**
     * code:mergeChangeColumnDetail
     * name:M1执行底层内容详情合并字段（特殊方法）
     * desc:undefined
     * gen by moon at 8/10/2022, 3:13:04 AM
     **/
    @Trace(operationName = "M1执行底层内容详情合并字段（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ImplementBaseContentDetailsMergeFieldsRespDto implementBaseContentDetailsMergeFields(ImplementBaseContentDetailsMergeFieldsReqDto reqDto) {
        ImplementBaseContentDetailsMergeFieldsRespDto retData = new ImplementBaseContentDetailsMergeFieldsRespDto();
        BeanUtil.copyProperties(reqDto, retData);
        if (reqDto.getBaseChangeColList() == null) {
            return retData;
        }

        Map<String, Field> fieldIndex = new HashMap<>();
        Field[] declaredFields = retData.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            fieldIndex.put(field.getName(), field);
        }

        for (BaseChangeColDto baseChange : reqDto.getBaseChangeColList()) {
            Field fileObj = fieldIndex.get(baseChange.getObjectPropertyCode());
            fileObj.setAccessible(true);
            try {
                fileObj.set(retData, baseChange.getMetaDataColumnContent());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return retData;
    }

    /**
     * code:receptionService
     * name:M1批量回写底层框架主表变更字段（特殊方法）
     * desc:undefined
     * gen by CHS
     **/
    @Trace(operationName = "M1批量回写底层框架主表变更字段（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public BatchWriteBackBaseMainTableChangeColRespDto batchWriteBackBaseMainTableChangeCol(BatchWriteBackBaseMainTableChangeColReqDto reqDto) {
        try {
            Map<String, String> sqlInfo = new HashMap<>();

            Map<String, ChangeColumnDto> newCol = new HashMap<>();
            for (ChangeColumnDto col : reqDto.getBaseMainTableChangeColList()) {
                if (newCol.containsKey(col.getEntityId() + col.getObjectPropertyCode())) {
                    ChangeColumnDto exisitDto = newCol.get(col.getEntityId() + col.getObjectPropertyCode());
                    if (exisitDto.getOperateTime().compareTo(col.getOperateTime()) >= 0) {
                        newCol.put(col.getEntityId() + col.getObjectPropertyCode(), col);
                    }
                } else {
                    newCol.put(col.getEntityId() + col.getObjectPropertyCode(), col);
                }
            }
            if (newCol.size() == 0) {
                return new BatchWriteBackBaseMainTableChangeColRespDto();
            }
            for (ChangeColumnDto col : newCol.values()) {
                //表名称
                String tableName = col.getTableTypeCode();
                //主键字段名称
                String priKeyFieldName = CommonFunctionHelper.humpToUnderline(col.getEntityName());
                //主键字段值
                String priKeyValue = col.getEntityId();
                String indexKey = tableName + ":" + priKeyFieldName + ":" + priKeyValue;
                if (!sqlInfo.containsKey(indexKey)) {
                    sqlInfo.put(indexKey, "");
                }
                String upKey = CommonFunctionHelper.humpToUnderline(col.getObjectPropertyCode());
                String upValue = col.getMetaDataColumnContent();
                //拼接sql
                String filedExpr = sqlInfo.get(indexKey) + upKey + "=" + "'" + upValue + "'" + ",";
                sqlInfo.put(indexKey, filedExpr);
            }

            for (Map.Entry<String, String> oneSqlFieldExpr : sqlInfo.entrySet()) {
                String tableName = oneSqlFieldExpr.getKey().split(":")[0];
                String priKeyFieldName = oneSqlFieldExpr.getKey().split(":")[1];
                String priKeyValue = oneSqlFieldExpr.getKey().split(":")[2];
                String filedExprGroup = oneSqlFieldExpr.getValue().substring(0, oneSqlFieldExpr.getValue().length() - 1);
                String sqlStr = "update " + tableName + " set " + filedExprGroup + " where " + CommonFunctionHelper.humpToUnderline(priKeyFieldName) + " = " + priKeyValue;
                Statement st = dataSource.getConnection().createStatement();
                st.execute(sqlStr);
                st.close();
            }


        } catch (Exception e) {
            throw new BizException("-1", e.getMessage(), false);
        } finally {
            try {
                dataSource.getConnection().close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return new BatchWriteBackBaseMainTableChangeColRespDto();
    }

    /**
     * code:generateSemanticInstance
     * name:M1-生成变更字段语义故事内容
     * desc:undefined
     * gen by moon at 9/1/2022, 4:05:11 PM
     **/
    @Trace(operationName = "M1-生成变更字段语义故事内容")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public QueryReceiveFieldDetailRespDto queryReceiveFieldDetail(QueryReceiveFieldDetailReqDto reqDto) {
        return BeanUtil.toBean(reqDto, QueryReceiveFieldDetailRespDto.class);
    }

    /**
     * code:generateSemanticInstance
     * name:M1-生成变更字段语义故事内容
     * desc:undefined
     * gen by moon at 9/1/2022, 7:07:33 PM
     **/
    @Trace(operationName = "M1-生成变更字段语义故事内容")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public AutoAenerateSemanticContentRespDto autoAenerateSemanticContent(AutoAenerateSemanticContentReqDto reqDto) {
        //ADD_SUBJECT_CONT
        //ARCHIVE_SUBJECT_CONT
        //SUBJECT_CHANGE_CONT
        boolean bRetFlag = false;
        AutoAenerateSemanticContentRespDto retData = new AutoAenerateSemanticContentRespDto();
        String retConent = "";
        QuerySemanticEngineDetailReqDto querySemanticEngineDetailReqDto = new QuerySemanticEngineDetailReqDto();
        querySemanticEngineDetailReqDto.setTemplateSemanticEngineCode("ADD_SUBJECT_CONT");
        QuerySemanticEngineDetailRespDto querySemanticEngineDetailRespDto = fwCompTemplateEngineClient.querySemanticEngineDetail(querySemanticEngineDetailReqDto).getData();
        if (querySemanticEngineDetailRespDto != null && querySemanticEngineDetailRespDto.getTemplateEngineTemplate() != null) {
            String addBehaviorNameTag = "\\{addBehaviorName}";
            String addSubjectContent = "\\{addSubjectContent}";
            String subjectContAffiliationParentCont = "\\{subjectContAffiliationParentCont}";
            if (reqDto.getAddBehaviorName() != null && !reqDto.getAddBehaviorName().isEmpty()) {
                bRetFlag = true;
                retConent = querySemanticEngineDetailRespDto.getTemplateEngineTemplate().replaceAll(addBehaviorNameTag, reqDto.getAddBehaviorName());
            } else {
                retConent = querySemanticEngineDetailRespDto.getTemplateEngineTemplate().replaceAll(addBehaviorNameTag, "---");
            }

            if (reqDto.getAddSubjectContent() != null && !reqDto.getAddSubjectContent().isEmpty()) {
                retConent = retConent.replaceAll(addSubjectContent, reqDto.getAddSubjectContent());
            } else {
                retConent = retConent.replaceAll(addSubjectContent, "---");
            }

            if (reqDto.getSubjectContAffiliationParentCont() != null && !reqDto.getSubjectContAffiliationParentCont().isEmpty()) {
                retConent = retConent.replaceAll(subjectContAffiliationParentCont, reqDto.getSubjectContAffiliationParentCont());
            } else {
                retConent = retConent.replaceAll(subjectContAffiliationParentCont, "---");
            }


            if (retConent != null && !retConent.isEmpty()) {
                retConent = retConent.replaceAll("---", "");
                retConent = retConent.replaceAll("（）", "");
                retData.setObjectName(retConent);
            }

            if (bRetFlag) {
                return retData;
            }

        }

        retConent = "";
        QuerySemanticEngineDetailReqDto querySemanticEngineDetailReqDto_2 = new QuerySemanticEngineDetailReqDto();
        querySemanticEngineDetailReqDto_2.setTemplateSemanticEngineCode("ARCHIVE_SUBJECT_CONT");
        QuerySemanticEngineDetailRespDto querySemanticEngineDetailRespDto_2 = fwCompTemplateEngineClient.querySemanticEngineDetail(querySemanticEngineDetailReqDto_2).getData();
        if (querySemanticEngineDetailRespDto_2 != null && querySemanticEngineDetailRespDto_2.getTemplateEngineTemplate() != null) {
            String archiveBehaviorName = "\\{archiveBehaviorName}";
            String archiveSubjectContent = "\\{archiveSubjectContent}";
            String subjectContAffiliationParentCont = "\\{subjectContAffiliationParentCont}";
            if (reqDto.getArchiveBehaviorName() != null && !reqDto.getArchiveBehaviorName().isEmpty()) {
                bRetFlag = true;
                retConent = querySemanticEngineDetailRespDto_2.getTemplateEngineTemplate().replaceAll(archiveBehaviorName, reqDto.getArchiveBehaviorName());
            } else {
                retConent = querySemanticEngineDetailRespDto_2.getTemplateEngineTemplate().replaceAll(archiveBehaviorName, "---");
            }

            if (reqDto.getArchiveSubjectContent() != null && !reqDto.getArchiveSubjectContent().isEmpty()) {
                retConent = retConent.replaceAll(archiveSubjectContent, reqDto.getArchiveSubjectContent());
            } else {
                retConent = retConent.replaceAll(archiveSubjectContent, "---");
            }

            if (reqDto.getSubjectContAffiliationParentCont() != null && !reqDto.getSubjectContAffiliationParentCont().isEmpty()) {
                retConent = retConent.replaceAll(subjectContAffiliationParentCont, reqDto.getSubjectContAffiliationParentCont());
            } else {
                retConent = retConent.replaceAll(subjectContAffiliationParentCont, "---");
            }

            if (retConent != null && !retConent.isEmpty()) {
                retConent = retConent.replaceAll("---", "");
                retConent = retConent.replaceAll("（）", "");
                retData.setObjectName(retConent);
            }

            if (bRetFlag) {
                return retData;
            }
        }

        retConent = "";
        QuerySemanticEngineDetailReqDto querySemanticEngineDetailReqDto_3 = new QuerySemanticEngineDetailReqDto();
        querySemanticEngineDetailReqDto_3.setTemplateSemanticEngineCode("SUBJECT_CHANGE_CONT");
        QuerySemanticEngineDetailRespDto querySemanticEngineDetailRespDto_3 = fwCompTemplateEngineClient.querySemanticEngineDetail(querySemanticEngineDetailReqDto_3).getData();
        if (querySemanticEngineDetailRespDto_3 != null && querySemanticEngineDetailRespDto_3.getTemplateEngineTemplate() != null) {
            String reviseSubjectContent = "\\{reviseSubjectContent}";
            String reviseBehaviorName = "\\{reviseBehaviorName}";
            String columnContent = "\\{columnContent}";
            if (reqDto.getReviseSubjectContent() != null && !reqDto.getReviseSubjectContent().isEmpty()) {
                bRetFlag = true;
                retConent = querySemanticEngineDetailRespDto_3.getTemplateEngineTemplate().replaceAll(reviseSubjectContent, reqDto.getReviseSubjectContent());
            } else {
                retConent = querySemanticEngineDetailRespDto_3.getTemplateEngineTemplate().replaceAll(reviseSubjectContent, "---");
            }

            if (reqDto.getReviseBehaviorName() != null && !reqDto.getReviseBehaviorName().isEmpty()) {
                retConent = retConent.replaceAll(reviseBehaviorName, reqDto.getReviseBehaviorName());
            } else {
                retConent = retConent.replaceAll(reviseBehaviorName, "---");
            }

            if (reqDto.getColumnContent() != null && !reqDto.getColumnContent().isEmpty()) {
                retConent = retConent.replaceAll(columnContent, reqDto.getColumnContent());
            } else {
                retConent = retConent.replaceAll(columnContent, "---");
            }

            if (retConent != null && !retConent.isEmpty()) {
                retConent = retConent.replaceAll("---", "");
                retConent = retConent.replaceAll("（）", "");
                retData.setObjectName(retConent);
            }

            if (bRetFlag) {
                return retData;
            }
        }

        return retData;
    }

    /**
     * code:filterUpdateFieldPrimaryKey
     * name:M1-1-02执行筛选更新字段主键（特殊方法）
     * desc:undefined
     * gen by moon at 9/5/2022, 1:48:44 AM
     **/
    @Trace(operationName = "M1-1-02执行筛选更新字段主键（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ImplementScreenUpdateFieldFkRespDto implementScreenUpdateFieldFk(ImplementScreenUpdateFieldFkReqDto reqDto) {
        ImplementScreenUpdateFieldFkRespDto retData = new ImplementScreenUpdateFieldFkRespDto();
        if (reqDto == null || reqDto.getBaseChangeColumnList() == null || reqDto.getBaseChangeColumnList().size() == 0) {
            return retData;
        }
        com.wicket.okrframework.base.service.dto.common.BaseChangeColumnDto oneElm = reqDto.getBaseChangeColumnList().get(0);
        if (oneElm.getTableTypeCode() == null || oneElm.getTableTypeCode().isEmpty()) {
            return retData;
        } else if (oneElm.getTableTypeCode().equals("OMS_ORG_DEPT")) {
            retData.setDeptId(oneElm.getEntityId());
        } else if (oneElm.getTableTypeCode().equals("OMS_ORG_INDUCTION_RECORD")) {
            retData.setInductionRecordId(oneElm.getEntityId());
        }
        return retData;
    }

    private DeptDto buildDept(BaseChangeColumnDto column) {
        DeptDto retData = new DeptDto();
        retData.setDeptId(column.getEntityId());
        if (column.getObjectPropertyCode() == null) {
            return retData;
        } else if (column.getObjectPropertyCode().equals("roleMemberId")) {
            retData.setRoleMemberId(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("directorInductionId")) {
            retData.setDirectorInductionId(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptNumber")) {
            retData.setDeptNumber(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptName")) {
            retData.setDeptName(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptEnName")) {
            retData.setDeptEnName(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptShortName")) {
            retData.setDeptShortName(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptDutyDesc")) {
            retData.setDeptDutyDesc(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptTargetDesc")) {
            retData.setDeptTargetDesc(column.getMetaDataColumnContent());
        }
        return retData;
    }

    private void updateDept(DeptDto dept, BaseChangeColumnDto column) {
        if (column.getObjectPropertyCode() == null) {
            return;
        } else if (column.getObjectPropertyCode().equals("roleMemberId")) {
            dept.setRoleMemberId(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("directorInductionId")) {
            dept.setDirectorInductionId(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptNumber")) {
            dept.setDeptNumber(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptName")) {
            dept.setDeptName(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptEnName")) {
            dept.setDeptEnName(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptShortName")) {
            dept.setDeptShortName(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptDutyDesc")) {
            dept.setDeptDutyDesc(column.getMetaDataColumnContent());
        } else if (column.getObjectPropertyCode().equals("deptTargetDesc")) {
            dept.setDeptTargetDesc(column.getMetaDataColumnContent());
        }
        return;
    }

    /**
     * code:concatenateMasterTableRevisionRecords
     * name:M1-1-02执行拼接主表修订记录（特殊方法）
     * desc:undefined
     * gen by moon at 9/5/2022, 1:48:46 AM
     **/
    @Trace(operationName = "M1-1-02执行拼接主表修订记录（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ImplementSplicingMainTableRevisionRecordRespDto implementSplicingMainTableRevisionRecord(ImplementSplicingMainTableRevisionRecordReqDto reqDto) {
        ImplementSplicingMainTableRevisionRecordRespDto retData = new ImplementSplicingMainTableRevisionRecordRespDto();
        Map<String, BaseChangeColumnDto> inducPool = new HashMap<>();
        Map<String, BaseChangeColumnDto> deptPool = new HashMap<>();
        for (com.wicket.okrframework.base.service.dto.common.BaseChangeColumnDto oneColumn : reqDto.getBaseChangeColumnList()) {
            if (oneColumn.getTableTypeCode().equals("OMS_ORG_INDUCTION_RECORD")) {
                //就职记录只有一个字段，如果后续会有多个字段，需要按照部门的方式处理
                BaseChangeColumnDto exisitElm = inducPool.get(oneColumn.getEntityId());
                if (exisitElm == null) {
                    inducPool.put(oneColumn.getEntityId(), BeanUtil.toBean(oneColumn, BaseChangeColumnDto.class));
                } else if (exisitElm.getOperateTime().compareTo(oneColumn.getOperateTime()) <= 0) {
                    inducPool.put(oneColumn.getEntityId(), BeanUtil.toBean(oneColumn, BaseChangeColumnDto.class));
                }
            } else if (oneColumn.getTableTypeCode().equals("OMS_ORG_DEPT")) {
                //部门有多个字段，所以map中的key要按主键id+字段名称的方式来建立
                BaseChangeColumnDto exisitElm = deptPool.get(oneColumn.getEntityId() + oneColumn.getObjectPropertyCode());
                if (exisitElm == null) {
                    deptPool.put(oneColumn.getEntityId() + oneColumn.getObjectPropertyCode(), BeanUtil.toBean(oneColumn, BaseChangeColumnDto.class));
                } else if (exisitElm.getOperateTime().compareTo(oneColumn.getOperateTime()) <= 0) {
                    deptPool.put(oneColumn.getEntityId() + oneColumn.getObjectPropertyCode(), BeanUtil.toBean(oneColumn, BaseChangeColumnDto.class));
                }
            }
        }
        for (BaseChangeColumnDto oneElm : inducPool.values()) {
            OrgInductionRecordDto inducElm = new OrgInductionRecordDto();
            inducElm.setInductionRecordId(oneElm.getEntityId());
            inducElm.setDirectorInductionRecordId(oneElm.getMetaDataColumnContent());
            retData.getOrgInductionRecordList().add(inducElm);
        }

        Map<String, DeptDto> deptInfo = new HashMap<>();
        for (BaseChangeColumnDto oneElm : deptPool.values()) {
            DeptDto exisitElm = deptInfo.get(oneElm.getEntityId());
            if (exisitElm == null) {
                DeptDto oneDept = buildDept(oneElm);
                deptInfo.put(oneElm.getEntityId(), oneDept);
            } else {
                updateDept(exisitElm, oneElm);
            }
        }
        retData.setDeptList(deptInfo.values().stream().map(p -> BeanUtil.toBean(p, DeptDto.class)).collect(Collectors.toList()));
        return retData;
    }


    //手工接入方法
}
